<?php
namespace Core\Mvc\Entity\Adapter;

use Core\Forms\Form;
use Core\Mvc\Entity\EntityInterface;
use Phalcon\Di;
use Phalcon\Mvc\User\Plugin;

/**
 * Class ConfigList
 * @package Core\Mvc\Entity\Adapter
 * @property \Phalcon\Flash\Direct $flash
 * @property \Phalcon\Flash\Session $flashSession
 * @property \Core\Config $config
 * @property \Core\Forms\Form $_form;
 */
class ConfigList extends Plugin implements EntityInterface
{
    /**
     * @var
     */
    protected $_field;
    /**
     * @var \Core\Forms\Form
     */
    protected $_form;
    /**
     * @var null | bool
     */
    protected $_save = null;
    /**
     * @var
     */
    protected $_id = '';

    /**
     * @var string
     */
    protected $_entity;

    /**
     * @var string
     */
    protected $_module;

    /**
     * @var
     */
    protected $_data;
    /**
     * @var
     */
    protected $_links;
    /**
     * @var string
     */
    protected $_storage;
    /**
     * @var string
     */
    public $contentModel;

    /**
     * @return string
     */
    public function getEntity()
    {
        return $this->_entity;
    }

    /**
     * @return string
     */
    public function getTitle(): string
    {
        if (!$this->getId()) {
            return '';
        }
        $field = formFieldInit($this->getField());
        foreach ($field as $key => $element) {
            if (isset($element['isTitle']) && $element['isTitle'] === true) {
                return (isset($this->{$key}) && $this->{$key}) ? $this->{$key} : '';
            }
        }
        return '';
    }

    /**
     * @param string $storage
     * @return $this
     */
    public function setStorage(string $storage)
    {
        $this->_storage = $storage;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getStorage()
    {
        return $this->_storage;
    }

    /**
     * @param array $links
     * @return $this
     */
    public function setLinks(array $links)
    {
        $this->_links = $links;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getLinks()
    {
        $this->eventsManager->fire('entity:links', $this, $this->_links);
        return $this->_links;
    }

    /**
     * @return mixed
     */
    public function links()
    {
        $this->eventsManager->fire('entity:links', $this);
        return $this->_links;
    }

    /**
     * @return null
     */
    public function getSaveState()
    {
        return $this->_save;
    }

    /**
     * @param string $contentModel
     * @return $this
     */
    public function setContentModel(string $contentModel)
    {
        $this->contentModel = $contentModel;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getContentModel()
    {
        return $this->contentModel;
    }

    /**
     * @param string $module
     * @return $this
     */
    public function setModule(string $module)
    {
        $this->_module = $module;
        return $this;
    }

    /**
     * @return string
     */
    public function getModule(): string
    {
        return $this->_module;
    }

    /**
     * @param null $contentModel
     * @return $this
     * @throws \Exception
     */
    public function setField($contentModel = null)
    {
        if ($this->_field && is_string($this->_field)) {
            $this->_field = $this->config->get($this->_field, []);
            $baseField = $this->config->get($this->_module . '.' . $this->_entity . 'BaseField', []);
            $this->_field = array_merge($this->_field, $baseField);
            return $this;
        }
        if (is_null($contentModel)) {
            if (!$this->contentModel) {
                throw new \Exception('参数错误，没有设置内容模型');
            } else {
                $contentModel = $this->contentModel;
            }
        }

        $contentModelList = $this->entityManager->contentModel($this->_entity);
        if (!isset($contentModelList[$contentModel])) {
            throw new \Exception('内容类型' . $contentModel . '不存在' . $this->_entity);
        }
        $field = isset($contentModelList[$contentModel]['field']) ? $contentModelList[$contentModel]['field'] : [];
        if (is_string($field)) {
            $this->_field = $this->config->get($field, []);
        }
        $baseField = $this->config->get($this->_module . '.' . $this->_entity . 'BaseField', []);
        $this->_field = array_merge($baseField,$this->_field);
        if (!is_array($this->_field)) {
            throw new \Exception('字段设置失败');
        }
        return $this;
    }

    /**
     * @return mixed
     */
    public function getField()
    {
        return $this->_field;
    }

    /**
     * @param $id
     */
    public function setId($id)
    {
        $this->_id = $id;
    }

    /**
     * @return string
     */
    public function getId(): string
    {
        return $this->_id;
    }

    /**
     * @return \Core\Forms\Form
     * @throws \Exception
     */
    public function addForm()
    {
        if (!$this->_field) {
            $this->setField();
        }
        if (!$this->_field) {
            throw new \Exception('还没有设置字段数据');
        }

        $this->eventsManager->fire('entity:addForm', $this);
        $this->_form = $this->form->create($this->_field);
        if ($this->_form->isValid()) {
            $this->save();
        }
        return $this->_form;
    }

    /**
     * @return \Core\Forms\Form
     * @throws \Exception
     */
    public function editForm()
    {
        if (!$this->_field || (is_string($this->_field) && $this->_field)) {
            $this->setField();
        }
        if (!$this->_field) {
            throw new \Exception('还没有设置字段数据');
        }
        $this->eventsManager->fire('entity:editForm', $this);
        $this->_form = $this->form->create($this->_field, $this->toArray());
        if ($this->_form->isValid()) {
            $this->save();
        }
        return $this->_form;
    }

    /**
     * @return mixed
     */
    public function getForm()
    {
        return $this->_form;
    }

    /**
     * @param $form
     * @return $this
     */
    public function setForm(Form $form)
    {
        $this->_form = $form;
        return $this;
    }

    /**
     * @return bool
     */
    public function delete()
    {
        if (!$this->_id || !$this->contentModel) {
            return false;
        }
        $configListContentModel = $this->config->cache('configListContentModel', []);
        $storage = $configListContentModel[$this->contentModel]['storage'];
        //菜单列表、术语类型列表
        $nodeList = $this->config->get($storage);
        if (!isset($nodeList[$this->_id])) {
            return false;
        }
        unset($nodeList[$this->_id]);
        return $this->config->set($storage, $nodeList);
    }

    /**
     * @return ConfigList | bool
     */
    public function save()
    {
        if (!isset($this->_storage)) {
            $this->flashSession->error('内容类型没有设置storage保存位置');
            return false;
        }
        $this->eventsManager->fire('entity:saveBefore', $this);
        $data = $this->_form->getData();
        $saveStorage = $this->_storage;
        $dataList = $this->config->get($saveStorage);
        if ($this->_id) {
            $data['id'] = $this->_id;
            $dataList[$this->_id] = $data;
        } elseif (isset($data['id'])) {
            $dataList[$data['id']] = $data;
        }
        if ($this->config->set($saveStorage, $dataList)) {
            $this->_save = true;
        } else {
            $this->_save = false;
        }
        $this->eventsManager->fire('entity:saveAfter', $this);
        return $this;
    }

    /**
     * @return array
     */
    public function toArray()
    {
        return (array)$this->_data;
    }

    /**
     * @param $data
     */
    public function setData($data)
    {
        $this->_data = $data;
    }

    /**
     * @param null|array $params
     * @return \Generator
     * @throws \Exception
     */
    public static function find(array $params = null)
    {
        if (!isset($params['_entity']) || !is_string($params['_entity'])) {
            throw new \Exception('没有设置实体机读名');
        }
        $entity = $params['_entity'];
        $di = Di::getDefault();
        $contentModel = $params['contentModel'];
        $configServer = $di->getShared('config');
        //configList实体类型，菜单、术语类型等。
        $configListContentModel = $di->getShared('entityManager')->contentModel($entity);
        if (is_null($contentModel) || !isset($configListContentModel[$contentModel])) {
            throw new \Exception('内容类型为' . $contentModel . '的configList实体不存在。');
        }
        $storage = $configListContentModel[$contentModel]['storage'];
        //菜单列表、术语类型列表
        $configData = $configServer->get($storage, []);
        foreach ($configData as $key => $config) {
            $configObject = $di->getShared('entityManager')->get($entity);
            if (!($configObject instanceof ConfigList)) {
                throw new \Exception('实体类型或许不存在');
            }
            $configObject->setId($key);
            $configObject->setContentModel($contentModel);
            foreach ($config as $cvk => $cvv) {
                $configObject->{$cvk} = $cvv;
            }
            $configObject->setStorage($storage);
            $configObject->setData($config);
            yield $configObject;
        }
    }

    /**
     * @param array|null $params
     * @return bool
     * @throws \Exception
     */
    public static function findFirst(array $params = null)
    {
        //print_r($params);
        if (!isset($params['_entity']) || !is_string($params['_entity'])) {
            throw new \Exception('没有设置实体机读名');
        }
        $entity = $params['_entity'];
        if (!is_array($params) || !isset($params['contentModel']) || !isset($params['id'])) {
            return false;
        }
        $di = Di::getDefault();
        $configServer = $di->getShared('config');
        //configList实体类型，菜单、术语类型等。
        $configListContentModel = $di->getShared('entityManager')->contentModel($entity);
        if (!isset($configListContentModel[$params['contentModel']])) {
            return false;
        }
        $storage = $configListContentModel[$params['contentModel']]['storage'];
        //菜单列表、术语类型列表
        $nodeList = $configServer->get($storage, []);
        if (!isset($nodeList[$params['id']])) {
            return false;
        }
        $data = $nodeList[$params['id']];
        $configObject = $di->getShared('entityManager')->get($entity);
        if (!($configObject instanceof ConfigList)) {
            throw new \Exception('实体类型或许不存在');
        }
        $configObject->setId($params['id']);
        $configObject->setContentModel($params['contentModel']);
        foreach ($data as $cvk => $cvv) {
            $configObject->{$cvk} = $cvv;
        }
        $configObject->setStorage($storage);
        $configObject->setData($data);
        $configObject->setField();
        return $configObject;
    }

}
